local skynet = require "skynet"
local log = require "sky_log"
--local skynet_db_tool = require "skynet_db_tool"
local def = require "srv_define"
local logic = {}

------------------------------------------------------------
--该游戏文件
function logic.Init(mode)
    --游戏模式 0正常局，-1回收，1赠送
    logic.mode = mode
    logic.cards = {}
    ---[[
    for _, v in pairs(def.cards) do
        table.insert(logic.cards, v)
    end
    --]]
end

--发指定牌
function logic.SendTestCards(TEST_OPEN, playerId)
    if TEST_OPEN==false then 
        log.info("11111")
        return
    end
    
    --读文件
    local file = io.open("./game/ermj/ermj_fapai.lua", "r")
    --os.execute("pwd") --执行
    --os.execute('ls')
    --local t = io.popen('pwd')
    --local a = t:read("*all")
    --log.info("a=", a)
    if file==nil then 
        log.info("2222222")
        return
    end
    local str = file:read('*all')
    file:close()
    local Cards = {}
    for k, v in string.gmatch(str, "%[%\"(%w+)%\"%]%s*=%s*([^, ]*)") do
        Cards[k] = v
    end
    local testTable = {}
    testTable.playerId = tonumber(Cards.playerId)
    testTable.cards = {}
    for i=1, 13 do
        local key = "card"..i
        if Cards[key]~=nil then 
            table.insert(testTable.cards, tonumber(Cards[key]))
        end
    end
    testTable.leftCard = tonumber(Cards.leftCard)
    testTable.faPai = {}
    for i=1, 6 do
        local key = "faPai"..i
        if Cards[key]~=nil then 
            table.insert(testTable.faPai, tonumber(Cards[key]))
        end
    end

    log.info("SendTestCards playerId=", playerId)
    log.info("SendTestCards testTable.playerId=", testTable.playerId)
    if playerId~=testTable.playerId then 
        return
    end

    --log.info("ChangeCards!!!!!!!!!!!!!!!!!!!!!!!!!")
    logic.ChangeCards(testTable.cards)

    --另一个玩家发牌时，将花牌和要发的牌拿走
    local leftPlayer = 1
    for i=1, leftPlayer do       --玩家数
        for j=1, 13 do
            local cardIndex = #logic.cards - (i*13+j) + 1
            --花牌或者是配牌里的牌就换掉
            if logic.cards[cardIndex]>=51 or logic.IsFaPai(logic.cards[cardIndex], testTable.faPai)==true then 
                local index = logic.ChangFapai(testTable.faPai)
                logic.cards[index], logic.cards[cardIndex] = logic.cards[cardIndex], logic.cards[index]
            end
        end
    end

    --要发的牌
    for k, v in ipairs(testTable.faPai) do
        local theIndex = #logic.cards - (leftPlayer+1)*13 - k + 1
        for i=1, theIndex do
            if logic.cards[i]==v then 
                logic.cards[theIndex], logic.cards[i] = logic.cards[i], logic.cards[theIndex]
                break
            end
        end
    end 
    
    ---[[
    --剩余牌数量
    if testTable.leftCard~=nil and testTable.leftCard>0 then 
        local tempCards = {}
        local firstIndex = #logic.cards - (13*(leftPlayer+1)+testTable.leftCard)
        for k, v in ipairs(logic.cards) do
            if k > firstIndex then 
                table.insert(tempCards, logic.cards[k])
            end
        end
        logic.cards = tempCards
    end
    --]]
    
    return true
end

function logic.IsFaPai(card, faPai) 
    for _, v in pairs(faPai) do
        if v==card then 
            return true
        end
    end

    return false
end

function logic.ChangFapai(faPai)
    local index
    for k, v in ipairs(logic.cards) do
        if v<51 and logic.IsFaPai(v, faPai)==false then 
            index = k
            break
        end
    end

    return index
end

--依据changeTable的顺序换牌到发牌位置
function logic.ChangeCards(changTable)
    if changTable==nil or #changTable==0 then 
        return
    end
    
    for k, v in ipairs(changTable) do
        for i=1, #logic.cards-k+1 do
            if logic.cards[i]==v then 
                logic.cards[#logic.cards-k+1], logic.cards[i] = logic.cards[i], logic.cards[#logic.cards-k+1]
                break
            end
        end
    end 
end

--洗牌
function logic.RandCards()
    for k, v in pairs(logic.cards) do
        local index = math.random(1, #logic.cards) 
        local temp = logic.cards[k]
        logic.cards[k] = logic.cards[index]
        logic.cards[index] = temp
    end
    --再洗一次
    for k, v in pairs(logic.cards) do
        local index = math.random(1, #logic.cards) 
        local temp = logic.cards[k]
        logic.cards[k] = logic.cards[index]
        logic.cards[index] = temp
    end
end

function logic.GetNousefulCard(handCards)
    local theCard 
    for k=#logic.cards, 1, -1 do
        local card =  logic.cards[k]
        if card<=47 and handCards[card]==0 and ((handCards[card-1] and handCards[card-1]==0) or (handCards[card+1] and handCards[card+1]==0)) then 
            theCard = card
            logic.cards[#logic.cards], logic.cards[k] = logic.cards[k], logic.cards[#logic.cards]
        end
    end
    --log.info("theCard =", theCard)
    if theCard==nil then 
        theCard = logic.cards[#logic.cards]
    end
    return theCard
end

--发X张牌  n张数 noHua[true不发花牌] noGet不摸的牌
function logic.GetCardX(n, noHua, noGet, handCards, getNouseful, robotGetCards)
    if n==nil then 
        n = 1
    end

    local getCards = {}
    for i=1, n do
        if #logic.cards==0 then 
            break
        end

        local temp
        if getNouseful then 
            temp = logic.GetNousefulCard(handCards)
        else
            temp = logic.cards[#logic.cards]
        end

        --机器人获得赢得牌
        if robotGetCards then 
            for _, card in pairs(robotGetCards) do
                local find = false
                for k, v in pairs(logic.cards) do
                    if v==card then 
                        find = true
                        logic.cards[#logic.cards], logic.cards[k] = logic.cards[k], logic.cards[#logic.cards]
                        temp = logic.cards[#logic.cards]
                        break
                    end
                end
            end
        end

        --不摸花牌时
        ---[[
        if (noHua==true) and temp>=51 then  
            for k, v in pairs(logic.cards) do
                if v<51 then
                    logic.cards[#logic.cards], logic.cards[k] = logic.cards[k], logic.cards[#logic.cards]
                    temp = logic.cards[#logic.cards]
                    break
                end
            end
        end
        --]]

        --回收模式不摸胡的牌
        if noGet~=nil then 
            local getNoHucard = false 
            for _, v in pairs(noGet) do
                if v==temp then 
                    getNoHucard = true
                end
            end
            if getNoHucard then 
                for k, v in pairs(logic.cards) do
                    local find = false
                    for _, card in pairs(noGet) do
                        if card==v then 
                            find = true
                        end
                    end
                    if find==false then
                        logic.cards[#logic.cards], logic.cards[k] = logic.cards[k], logic.cards[#logic.cards]
                        temp = logic.cards[#logic.cards]
                        break
                    end
                end
            end
        end

        table.insert(getCards, temp)
        logic.cards[#logic.cards] = nil 
    end

    --log.info("GetCardX=", getCards)
    return getCards
end

--牌转换
function logic.CardToIndex(cardSource)
    --已转换检测
    if cardSource.isIndex==true then 
        return cardSource
    end
   
    local cards = {
        isIndex = true,          --已经转换的标志
        theCards = {},
    }
    for _, v in ipairs(def.cards) do
        cards.theCards[v] = 0
    end

    for _, v in pairs(cardSource) do
        cards.theCards[v] = cards.theCards[v] + 1
    end

    return cards.theCards
end

function logic.IndexToCard(handCards)
    local cards = {}
    for cardValue, cardNum in pairs(handCards) do
        if cardNum~=0 then 
            for i=1, cardNum do
                table.insert(cards, cardValue)
            end
        end 
    end

    return cards
end

function logic.GetLeftCardNum() 
    --log.info("logic.cards=", logic.cards)
    return #logic.cards
end

function logic.CopyHandCards(handCards)
    local theCards = {}

    for cardValue, cardNums in pairs(handCards) do
        theCards[cardValue] = cardNums
    end

    return theCards
end

--检查手牌中是否有该牌
function logic.CheckCardVaild(cards, theCards)
    --检测打的是否是花牌，花牌不允许打
    if theCards[1]>=51 then 
        return false
    end

    --检测打的牌是否正确
    local destCard = logic.CardToIndex(theCards)
    for k, v in pairs(destCard) do
        if cards[k] < destCard[k] then
            log.info("cards=", cards)
            log.info("destCard=", destCard)
            return false
        end
    end

    return true
end

--取刻子 （3张相同的牌）
function logic.GetKeZi(handCards)
    local keZi = {}
    for k, v in pairs(handCards) do
        if v>=3 then 
            handCards[k] = handCards[k] - 3
            local oneKe = {}
            for i=1, 3 do
                table.insert(oneKe, k)
            end
            table.insert(keZi, oneKe)
        end
    end

    return keZi
end

function logic.SortHandCards(handCards)
    local temp = {}
    for i=1, 58 do
        if handCards[i]~=nil then 
            temp[i] = handCards[i]
        end
    end

    return temp
end

--取顺子
function logic.GetShunZi(handCards)
    local shunZi = {}
    --for k, v in pairs(handCards) do
    for k=1, 39 do
        if handCards[k]~=nil then 
            --只算字牌
            if k<41 and handCards[k]>=1 then 
                local getNums = handCards[k]
                for i=1, getNums do
                    if (handCards[k+1] and handCards[k+1]>=1) and (handCards[k+2] and handCards[k+2]>=1) then 
                        local oneShun = {}
                        for j=0, 2 do
                            handCards[k+j] = handCards[k+j] - 1
                            table.insert(oneShun, k+j)
                        end
                        table.insert(shunZi, oneShun)
                    end
                end
            end 
        end
    end

    return shunZi
end

function logic.CheckHuJiubao(tempHandCards)
    local huInfo = {
        isHu = false,
        huJiang = {},
        huKezi = {},
        huShunzi = {},
    }

    --必须是这种模式，然后胡 1~9 （特殊胡法）
    local huCards = {
        11, 11, 11, 
        12, 13, 14,
        15, 16, 17,
        18,
        19, 19, 19,
    }

    --查手牌
    local tempCards = logic.CopyHandCards(tempHandCards)
    for _, card in pairs(huCards) do
        if tempCards[card]>0 then 
            tempCards[card] = tempCards[card] - 1
        else
            return huInfo
        end
    end

    --log.info("tempCards=", tempCards)

    --还剩最后一张，判断是否是1~9里任意一值
    for k, v in pairs(tempCards) do
        if v>0 then 
            if k>19 then 
                return huInfo
            end
        end
    end

    huInfo.isHu = true

    return huInfo
end

function logic.CheckHu(handCards, operCard)
    local huInfo = {
        isHu = false,
        huJiang = {},
        huKezi = {},
        huShunzi = {},
    }

    local tempHandCards = logic.CopyHandCards(handCards)
    if operCard~=nil then 
        tempHandCards[operCard] = tempHandCards[operCard] + 1
    end
    local tempHandCards2 = logic.CopyHandCards(tempHandCards) 

    --特殊胡牌：7对(7个对子)
    local duizi = 0
    for k, v in pairs(tempHandCards) do
        if v==2 then 
            duizi = duizi + 1
            table.insert(huInfo.huJiang, k)
        end
    end
    if duizi==7 then 
        huInfo.isHu = true 
        return huInfo
    end

    --特殊胡牌:九宝莲灯
    local jiuBaoInfo = logic.CheckHuJiubao(tempHandCards)
    --log.info("CheckHu jiubaoInfo=", jiuBaoInfo)
    if jiuBaoInfo.isHu==true then 
        return jiuBaoInfo
    end

    huInfo.huJiang = {}
    --分别计算以不同 "将" 情况下胡牌情况
    --log.info("CheckHu handCards=", tempHandCards)
    for k, v in pairs(tempHandCards) do
        if v>=2 then 
            local theCards = logic.CopyHandCards(tempHandCards)
            theCards[k] = theCards[k] - 2
            --log.info("after jiang handCards=", theCards)
            --先取所有顺子
            local shunzi = logic.GetShunZi(theCards)
            --log.info("after GetShunZi handCards=", theCards)
            --再取所有刻子
            local kezi = logic.GetKeZi(theCards)
            --log.info("after GetKeZi handCards=", theCards)

            --若手牌完全取完，则代表是胡牌
            local isHu = true
            for _, cardNums in pairs(theCards) do
                if cardNums > 0 then 
                    isHu = false
                end
            end
            --胡了
            if isHu then
                huInfo.isHu = true 
                huInfo.huJiang = {k}
                huInfo.huKezi = kezi
                huInfo.huShunzi = shunzi
                return huInfo
            end
        end
    end

    for k, v in pairs(tempHandCards2) do
        if v>=2 then 
            local theCards = logic.CopyHandCards(tempHandCards2)
            theCards[k] = theCards[k] - 2
            --log.info("after jiang handCards=", theCards)
            --先取所有刻子
            local kezi = logic.GetKeZi(theCards)
            --log.info("after GetKeZi handCards=", theCards)
            --再取所有顺子
            local shunzi = logic.GetShunZi(theCards)
            --log.info("after GetShunZi handCards=", theCards)
            
            --若手牌完全取完，则代表是胡牌
            local isHu = true
            for _, cardNums in pairs(theCards) do
                if cardNums > 0 then 
                    isHu = false
                end
            end
            --胡了
            if isHu then
                huInfo.isHu = true 
                huInfo.huJiang = {k}
                huInfo.huKezi = kezi
                huInfo.huShunzi = shunzi
                return huInfo
            end
        end
    end

    return huInfo
end

function logic.FillOneAction(oper_type, cards)
    local oneAction
    oneAction = {
        oper_type = oper_type, 
        oper_cards = cards
    }
    return oneAction
end

--检测自摸
function logic.CheckZimo(handCards, action, card)
    local huInfo = logic.CheckHu(handCards)
    if huInfo.isHu==true then 
        local oneAction = logic.FillOneAction(def.operType.zimo, {card})
        table.insert(action, oneAction)
    end
end

--这里的杠是指是  暗杠，补杠 (明杠不会由自己摸牌触发)
function logic.CheckGang(handCards, cardsCombo, action, card)
    --是不是补杠
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.peng then  
            for cardValue, cardNums in pairs(handCards) do
                if v.oper_cards[1]==cardValue and cardNums>0 then 
                    local oneAction = logic.FillOneAction(def.operType.buGang, {cardValue, cardValue, cardValue, cardValue})
                    table.insert(action, oneAction)
                end
            end
        end
    end

    --暗杠
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==4 then 
            local oneAction = logic.FillOneAction(def.operType.anGang, {cardValue, cardValue, cardValue, cardValue})
            table.insert(action, oneAction)
        end
    end
end

--摸牌后检测手牌牌型
function logic.GetCardCheck(handCards, cardsCombo, card)
    local action = {}
    --检测自摸
    logic.CheckZimo(handCards, action, card)
    --检测杠
    logic.CheckGang(handCards, cardsCombo, action, card)

     return action
end

--打牌检查打的牌是否合法
function logic.CheckOutCard(handCards, operCard)
    if logic.CheckCardVaild(handCards, operCard)==false then 
        log.error("CheckOutCard error!---->", operCard)
        return false
    end

    handCards[operCard[1]] = handCards[operCard[1]] - 1

    return true
end

--吃
function logic.CheckChi(handCards, operCard, action)
    --风箭花不吃
    if operCard>39 then 
        return
    end

    --左吃
    if (handCards[operCard-2]~=nil and handCards[operCard-2]>0) and (handCards[operCard-1]~=nil and handCards[operCard-1]>0) then
        local oneAction = logic.FillOneAction(def.operType.chi, {operCard-2, operCard-1, operCard})
        table.insert(action, oneAction)
    end
    --中吃
    if (handCards[operCard-1]~=nil and handCards[operCard-1]>0) and (handCards[operCard+1]~=nil and handCards[operCard+1]>0) then
        local oneAction = logic.FillOneAction(def.operType.chi, {operCard-1, operCard, operCard+1})
        table.insert(action, oneAction)
    end
    --右吃
    if (handCards[operCard+1]~=nil and handCards[operCard+1]>0) and (handCards[operCard+2]~=nil and handCards[operCard+2]>0) then
        local oneAction = logic.FillOneAction(def.operType.chi, {operCard, operCard+1, operCard+2})
        table.insert(action, oneAction)
    end
end

--碰
function logic.CheckPeng(handCards, operCard, action)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=2 and cardValue==operCard then 
            local oneAction = logic.FillOneAction(def.operType.peng, {cardValue, cardValue, cardValue})
            table.insert(action, oneAction)
        end
    end
end

--明杠
function logic.CheckMingGang(handCards, operCard, action)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==3 and cardValue==operCard then 
            local oneAction = logic.FillOneAction(def.operType.mingGang, {cardValue, cardValue, cardValue, cardValue})
            table.insert(action, oneAction)
        end
    end
end

--点炮胡
function logic.CheckDianPao(handCards, operCard, action)
    local huInfo = logic.CheckHu(handCards, operCard)
    if huInfo.isHu==true then 
        local oneAction = logic.FillOneAction(def.operType.dianPao, {operCard})
        table.insert(action, oneAction)
    end
end

--打出的牌检测是否触发其他人操作
function logic.OutCardCheck(handCards, operCard, tingCardsNum)
    local action = {}

    --听牌时吃碰就不检测了
    if tingCardsNum==0 then
        --检测吃
        logic.CheckChi(handCards, operCard, action)
        --检测碰
        logic.CheckPeng(handCards, operCard, action)
        --检测明杠
        logic.CheckMingGang(handCards, operCard, action)
    end
    --检测点炮胡
    logic.CheckDianPao(handCards, operCard, action)

    return action
end

--找对子
function logic.GetDuizi(handCards)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==2 then
            handCards[cardValue] = handCards[cardValue] - 2 
        end
    end
end

--

--得到最优出牌
function logic.GetBestOutCard(handCards, tingCards, lastGetCard, isRobot, playerHucards)
    --把牌里的对子，刻子，顺子去掉。剩下的就是单张，先打字牌，再打边张，1,9。都没有则随机打就行
    local theCards = logic.CopyHandCards(handCards) 
    logic.GetDuizi(theCards)
    logic.GetKeZi(theCards)
    logic.GetShunZi(theCards)
    --log.info("theCards=", theCards)

    local outCard
    for i=41, 47 do
        if theCards[i]>0 then 
            outCard = i
            break
        end
    end
   
    if outCard==nil and theCards[11]~=nil and theCards[11]>0 then 
        outCard = 11
    end
    if outCard==nil and theCards[19]~=nil and theCards[19]>0 then 
        outCard = 19
    end
    if outCard==nil and theCards[21]~=nil and theCards[21]>0 then 
        outCard = 21
    end
    if outCard==nil and theCards[29]~=nil and theCards[29]>0 then 
        outCard = 29
    end
    if outCard==nil and theCards[31]~=nil and theCards[31]>0 then 
        outCard = 31
    end
    if outCard==nil and theCards[39]~=nil and theCards[39]>0 then 
        outCard = 39
    end
   
    if outCard==nil then 
        for k, v in pairs(theCards) do
            if v>0 then
                outCard = k
                break
            end
        end
    end

    if tingCards~=nil and #tingCards~=0 then 
        outCard = lastGetCard
    end

    if isRobot==true then 
        --outCard = lastGetCard
    end

    --还是空，说明点了过胡，则摸啥打啥
    if outCard==nil then 
        outCard = lastGetCard
    end

    if outCard==nil or handCards[outCard]==nil or handCards[outCard]<=0 then 
        for k, v in pairs(handCards) do
            if v>0 then
                outCard = k
                break
            end
        end
    end

    --机器人不出玩家胡的牌
    if isRobot==true and playerHucards then 
        local find = false
        for _, v in pairs(playerHucards) do
            if outCard==v then 
                find = true
            end
        end
        if find==true then 
            for k, v in pairs(handCards) do
                if v>0 then 
                    local noHuCard = false
                    for _, card in pairs(playerHucards) do
                        if k==card then 
                            noHuCard = true
                        end
                    end
                    if noHuCard==false then
                        outCard = k
                    end
                end
            end
        end
    end
    
    return {outCard}
end

function logic.OutCardCheckTing(handCards)
    local tingCards = {}

    local tempCards = logic.CopyHandCards(handCards)
    for _, cards in pairs(def.cards) do
        local huInfo = logic.CheckHu(tempCards, cards)  
        if huInfo.isHu==true then 
            local hasInsert = false 
            for _, tingCard in pairs(tingCards) do
                if tingCard==cards then 
                    hasInsert = true
                    break
                end
            end
            if hasInsert==false then 
                table.insert(tingCards, cards)
            end
        end
    end

    return tingCards
end

function logic.CheckTingCardNums(card, allSeeCards)
    local nums = 0
    for _, v in pairs(allSeeCards) do
        if v==card then 
            nums = nums + 1
        end
    end
    

    local iRet = 4-nums
    if iRet<0 then 
        iRet = 0
    end

    return iRet
end

function logic.CheckTingFanNums(tempCards, tingCard, cardsCombo, specFan)
    local handCards = logic.CopyHandCards(tempCards)
    handCards[tingCard] = handCards[tingCard] + 1

    local fanxing = logic.CalcFan(handCards, cardsCombo)
    for _, v in pairs(specFan) do
        table.insert(fanxing, v)
    end
    fanxing = logic.CheckFanXingClash(fanxing)

    local fanxingValue = logic.CalcFanValueByFan(fanxing, 0)

    local fanNums = logic.CalcFanNumsByFan(fanxingValue)

    return fanNums
end

function logic.CheckTing(handCards, allSeeCards, cardsCombo, specFan)
    local tingCards = {}

    ---[[
    for outCard, v in pairs(handCards) do
        if v>0 then 
        --if outCard==19 then
            local tempCards = logic.CopyHandCards(handCards)
            tempCards[outCard] = tempCards[outCard] - 1 
            --log.info("tempCards=", tempCards)

            local oneTing = {
                out_card = def.maxValue,
                ting_cards = {},
            }
            for _, cards in pairs(def.cards) do
                --if cards==15 then 
                    local huInfo = logic.CheckHu(tempCards, cards) 
                    --log.info("huInfo=", huInfo)
                    if huInfo.isHu==true then 
                        local hasInsert = false 
                        for _, tingCard in pairs(oneTing.ting_cards) do
                            if tingCard.ting_card==cards then 
                                hasInsert = true
                                break
                            end
                        end
                        if hasInsert==false then 
                            local tingCardInfo = {}
                            tingCardInfo.ting_card = cards
                            tingCardInfo.left_nums = logic.CheckTingCardNums(cards, allSeeCards)
                            tingCardInfo.fan_Nums = logic.CheckTingFanNums(tempCards, cards, cardsCombo, specFan)
                            table.insert(oneTing.ting_cards, tingCardInfo)
                            oneTing.out_card = outCard
                        end
                    end
                --end
            end

            if oneTing.out_card~=def.maxValue then 
                table.insert(tingCards, oneTing)
            end
        end
    end
    --]]

    return tingCards
end

function logic.CalcFanNumsByFan(fanxingValue) 
    local fanNums = 0
    for _, v in pairs(fanxingValue) do
        fanNums = fanNums + v
    end

    return fanNums
end

--算番
function logic.CalcFan(handCards, cardsCombo)
    local huInfo = logic.CheckHu(handCards)

    local fanxing = {}
    --大四喜
    logic.CheckDaSiXi(fanxing, handCards, cardsCombo)
    --大三元
    logic.CheckDaSanYuan(fanxing, handCards, cardsCombo)
    --九宝莲灯
    logic.CheckJiuBao(fanxing, handCards, cardsCombo)
    --四杠
    logic.CheckSiGang(fanxing, handCards, cardsCombo)
    --连七对
    logic.CheckLianQiDui(fanxing, handCards, cardsCombo)
    --天胡
    --logic.CheckTianHu(fanxing, handCards, cardsCombo)
    --地胡
    --logic.CheckDiHu(fanxing, handCards, cardsCombo)
    --人胡
    --logic.CheckRenHu(fanxing, handCards, cardsCombo)
    --百万石
    logic.CheckBaiWanShi(fanxing, handCards, cardsCombo)
    --小四喜
    logic.CheckXiaoSiXi(fanxing, handCards, cardsCombo)
    --小三元
    logic.CheckXiaoSanYuan(fanxing, handCards, cardsCombo)
    --字一色
    logic.CheckZiYiSe(fanxing, handCards, cardsCombo)
    --四暗刻
    logic.CheckSiAnKe(fanxing, handCards, cardsCombo)
    --一色双龙会
    logic.CheckYiSeShuangLongHui(fanxing, handCards, cardsCombo)
    --一色四同顺
    logic.CheckYiSeSiTongShun(fanxing, handCards, cardsCombo)
    --一色四节高
    logic.CheckYiSeSiJieGao(fanxing, handCards, cardsCombo)
    --一色四步高
    logic.CheckYiSeSiBuGao(fanxing, handCards, cardsCombo)
    --三杠
    logic.CheckSanGang(fanxing, handCards, cardsCombo)
    --混九幺
    logic.CheckHunJiuYao(fanxing, handCards, cardsCombo)
    --七对
    logic.CheckQiDui(fanxing, handCards, cardsCombo)
    --清一色
    logic.CheckQingYiSe(fanxing, handCards, cardsCombo)
    --一色三同顺
    logic.CheckYiSeSanTongShun(fanxing, handCards, cardsCombo)
    --一色三节高
    logic.CheckYiSeSanJieGao(fanxing, handCards, cardsCombo)
    --清龙
    logic.CheckQingLong(fanxing, handCards, cardsCombo)
    --一色三步高
    logic.CheckYiSeSanBuGao(fanxing, handCards, cardsCombo)
    --三暗刻
    logic.CheckSanAnKe(fanxing, handCards, cardsCombo, huInfo)
    --天听
    --logic.CheckTianTing(fanxing, handCards, cardsCombo)
    --大于5
    logic.CheckDaYu5(fanxing, handCards, cardsCombo)
    --小于5
    logic.CheckXiaoYu5(fanxing, handCards, cardsCombo)
    --三风刻
    logic.CheckSanFengKe(fanxing, handCards, cardsCombo)
    --妙手回春
    --logic.CheckMiaoShou(fanxing, handCards, cardsCombo)
    --海底捞月
    --logic.CheckHaiDi(fanxing, handCards, cardsCombo)
    --杠上开花
    --logic.CheckGangHua(fanxing, handCards, cardsCombo)
    --碰碰胡
    logic.CheckPengPeng(fanxing, handCards, cardsCombo)
    --混一色
    logic.CheckHunYiSe(fanxing, handCards, cardsCombo)
    --全求人
    --logic.CheckQuanQiuRen(fanxing, handCards, cardsCombo)
    --双暗杠
    logic.CheckShuangAnGang(fanxing, handCards, cardsCombo)
    --双箭刻
    logic.CheckShuangJianKe(fanxing, handCards, cardsCombo)
    --全带幺
    logic.CheckQuanDaiYao(fanxing, handCards, cardsCombo)
    --不求人
    --logic.CheckBuQiuRen(fanxing, handCards, cardsCombo)
    --双明杠
    logic.CheckShuangMingGang(fanxing, handCards, cardsCombo)
    --胡绝张
    --logic.CheckHuJueZhang(fanxing, handCards, cardsCombo)
    --立直
    --logic.CheckLiZhi(fanxing, handCards, cardsCombo)
    --箭刻
    logic.CheckJianKe(fanxing, handCards, cardsCombo)
    --圈风刻
    --logic.CheckQuanFengKe(fanxing, handCards, cardsCombo)
    --门风刻
    --logic.CheckMenFengKe(fanxing, handCards, cardsCombo)
    --门前清
    --logic.CheckMenQianQing(fanxing, handCards, cardsCombo)
    --平胡
    --logic.CheckPingHu(fanxing, handCards, cardsCombo)
    --四归
    logic.CheckSiGui(fanxing, handCards, cardsCombo)
    --双暗刻
    logic.CheckShuangAnKe(fanxing, handCards, cardsCombo)
    --暗杠
    logic.CheckAnGang(fanxing, handCards, cardsCombo)
    --断幺
    logic.CheckDuanYao(fanxing, handCards, cardsCombo)
    --一般高
    logic.CheckYiBanGao(fanxing, handCards, cardsCombo)
    --连6
    logic.CheckLianLiu(fanxing, handCards, cardsCombo)
    --老少副
    logic.CheckLaoShaoFu(fanxing, handCards, cardsCombo)
    --幺九刻
    logic.CheckYaoJiuKe(fanxing, handCards, cardsCombo)
    --明杠
    logic.CheckMingGangFan(fanxing, handCards, cardsCombo)

    return fanxing
end

function logic.CalcFanValueByFan(fanxing, huaNums) 
    local fanxingValue = {}
    for _, v in ipairs(fanxing) do
        if v==def.fanXing.huaPai then 
            table.insert(fanxingValue, def.fanXingValue[v]*huaNums)
        else
            table.insert(fanxingValue, def.fanXingValue[v])
        end
    end

    return fanxingValue
end

--检测是否大四喜(由四副风刻(杠)组成的和牌。不记番：三风刻、碰碰胡、幺九刻)
function logic.CheckDaSiXi(fanxing, handCards, cardsCombo)
    local fengTable = {}
    fengTable[41] = false
    fengTable[42] = false
    fengTable[43] = false
    fengTable[44] = false
    --手牌找风牌  （东南西北）
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>=41 and cardValue<=44 then 
            if cardNums>=3 then 
                fengTable[cardValue] = true
            end
        end
    end
    --组成牌型找 风的碰杠
    for _, v in pairs(cardsCombo) do
        if v.oper_type>=def.operType.peng and v.oper_type<=def.operType.buGang then 
            if v.oper_cards[1]>=41 and v.oper_cards[1]<=44 then 
                fengTable[v.oper_cards[1]] = true
            end
        end
    end

    --4种风牌都有
    if fengTable[41]==true and fengTable[42]==true and fengTable[43]==true and fengTable[44]==true then 
        table.insert(fanxing, def.fanXing.daSiXi)
    end
end

--检测是否大三元(由中发白三幅刻子或杠组成的牌型；不记番：箭刻、双箭刻)
function logic.CheckDaSanYuan(fanxing, handCards, cardsCombo)
    local checkTable = {}
    checkTable[45] = false
    checkTable[46] = false
    checkTable[47] = false

    --手牌找中发白
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>=45 and cardValue<=47 then 
            if cardNums>=3 then 
                checkTable[cardValue] = true
            end
        end
    end
    --组成牌型找
    for _, v in pairs(cardsCombo) do
        if v.oper_type>=def.operType.peng and v.oper_type<=def.operType.buGang then 
            if v.oper_cards[1]>=45 and v.oper_cards[1]<=47 then 
                checkTable[v.oper_cards[1]] = true
            end
        end
    end

    --4种风牌都有
    if checkTable[45]==true and checkTable[46]==true and checkTable[47]==true then 
        table.insert(fanxing, def.fanXing.daSanYuan)
    end
end

--检测是否九宝连灯（由一种花色序牌组成按照1112345678999组成。不记番：清一色、不求人、门前清、幺九刻）
function logic.CheckJiuBao(fanxing, handCards, cardsCombo)
    local checkWan = true

    --必须是这种模式，然后胡 1~9 （特殊胡法）
    local huCards = {
        11, 11, 11, 
        12, 13, 14,
        15, 16, 17,
        18,
        19, 19, 19,
    }

    --查手牌
    local tempCards = logic.CopyHandCards(handCards)
    for _, card in pairs(huCards) do
        if tempCards[card]>0 then 
            tempCards[card] = tempCards[card] - 1
        else
            return 
        end
    end

    --还剩最后一张，判断是否是1~9里任意一值
    for _, v in pairs(tempCards) do
        if v>0 then 
            if v>19 then 
                return 
            end
        end
    end
    
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type~=def.operType.anGang then 
            return
        end
    end

    table.insert(fanxing, def.fanXing.jiuBao)
end

--检测是否四杠(和牌时,牌里有4组杠,眀暗杠均可(不计双暗杠、双明杠、明杠、暗杠、单调) )
function logic.CheckSiGang(fanxing, handCards, cardsCombo)
    local gangNums = 0
    --只检查已组成的杠
    --[[
    for cardValue, cardNums in pairs(handCards) do
        --是不是有4个
        if cardNums==4 then 
            gangNums = gangNums + 1
        end
    end
    --]]

    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.mingGang or v.oper_type==def.operType.anGang or v.oper_type==def.operType.buGang then 
            gangNums = gangNums + 1
        end
    end

    if gangNums==4 then 
        table.insert(fanxing, def.fanXing.siGang)
    end
end

--检测是否连7对 (胡牌时,牌里有顺序相连的7个对子(不计清一色、不求人、单调、门清、七对、连六、一般高) )
function logic.CheckLianQiDui(fanxing, handCards, cardsCombo)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=2 and cardValue<41 then
            local find = true
            for i=0, 6 do
                if handCards[cardValue+i]==nil or handCards[cardValue+i]<2 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.lian7dui)
                return
            end
        end
    end
end

--检测是否百万石 和牌时(注意:牌型符合和牌基本牌型规则),所有牌由万字牌组成,且将牌面的数字相加,总和超过100(包含100)称为百万石(不计清一色)）
function logic.CheckBaiWanShi(fanxing, handCards, cardsCombo)
    local result = true
    local sum = 0
    --手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums > 0 then 
            if cardValue<=19 then 
                for i=1, cardNums do
                    sum = sum + cardValue%10
                end
            else
                result = false
            end
        end
    end

    --组成牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]>19 then 
            result = false
        end
    end

    if result==true and sum>=100 then 
        table.insert(fanxing, def.fanXing.baiWanShi)
    end
end

--检测是否小四喜 (和牌时,牌里有3组风牌刻子(杠)和风牌的将牌(不计三风刻、幺九刻)
function logic.CheckXiaoSiXi(fanxing, handCards, cardsCombo)
    local fengNums = 0
    local fengJiang = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        --风牌只可能碰杠
        if v.oper_cards[1]>=41 and v.oper_cards[1]<=44 then 
            fengNums = fengNums + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        --是不是风牌  （东南西北）
        if cardValue>=41 and cardValue<=44 then 
            if cardNums>=3 then 
                fengNums = fengNums + 1
            elseif cardNums==2 then 
                fengJiang = fengJiang + 1
            end
        end
    end

    if fengNums>=3 and fengJiang>=1 then 
        table.insert(fanxing, def.fanXing.xiaoSiXi)
    end
end

--检测是否小三元 (和牌时,牌里有2组箭牌刻子(杠)和箭牌的将牌(不计箭刻、双箭刻、幺九刻))
function logic.CheckXiaoSanYuan(fanxing, handCards, cardsCombo)
    local jianNums = 0
    local jianJiang = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        --箭牌只可能碰杠
        if v.oper_cards[1]>=45 and v.oper_cards[1]<=47 then 
            jianNums = jianNums + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        --是不是箭牌  （中发白）
        if cardValue>=45 and cardValue<=47 then 
            if cardNums >= 2 then 
                if cardNums >= 3 then 
                    jianNums = jianNums + 1
                else
                    jianJiang = jianJiang + 1
                end
            end
            
        end
    end

    if jianNums>=2 and jianJiang>=1 then 
        table.insert(fanxing, def.fanXing.xiaoSanYuan)
    end
end

--检测是否字一色 (和牌时，牌全部为字牌的刻子（杠）以及字牌的将牌（不计碰碰胡、混么九、全带么、么九刻）)
function logic.CheckZiYiSe(fanxing, handCards, cardsCombo)
    local result = true
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]<41 then 
            result = false
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue<41 and cardNums>0 then 
            result = false
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.ziYiSe)
    end
end

--检测是否四暗刻 (和牌时，牌里有4组暗刻（不计门前清、碰碰和、三暗刻、双暗刻、不求人）)
function logic.CheckSiAnKe(fanxing, handCards, cardsCombo)
    local anKe = 0

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=3 then 
            anKe = anKe + 1
        end
    end

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.anGang then 
            anKe = anKe + 1
        end
    end

    if anKe>=4 then 
        table.insert(fanxing, def.fanXing.siAnKe)
    end
end

--检测是否一色双龙会 (和牌时，牌里由5万做将牌并有123万和789万的顺子各2组（不计平和、七对、清一色、一般高、老少副）)
function logic.CheckYiSeShuangLongHui(fanxing, handCards, cardsCombo)
    local theCards = {
        [11] = 2, [12] = 2, [13] = 2, [15] = 2,
        [17] = 2, [18] = 2, [19] = 2,
    }

    local result = true
    for k, v in pairs(theCards) do
        if handCards[k]~=v then 
            result = false
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.yiSeShuangLong)
    end
end

--检测是否一色四同顺 (和牌时，牌里有相同的4组顺子（不计一色三高、 一 般高、四归一、一色三同顺）)
function logic.CheckYiSeSiTongShun(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.chi then 
            for _, card in pairs(v.oper_cards) do
                tempCards[card] = tempCards[card] + 1
            end
        end
    end

    --相同的四组顺子其实就是4个连着的杠牌
    for cardValue, cardNums in pairs(tempCards) do
        if cardNums==4 and cardValue<41 then
            local find = true
            for i=0, 2 do
                if tempCards[cardValue+i]==nil or tempCards[cardValue+i]<4 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.yiSeSiTongShun)
                return
            end
        end
    end
end

--检测是否一色四节高 和牌时，牌里有4组依次递增1位数的刻子（不计一色三同顒、一色三节高、碰碰和）)
function logic.CheckYiSeSiJieGao(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.peng then 
            tempCards[v.oper_cards[1]] = tempCards[v.oper_cards[1]] + 3
        end
    end

    for cardValue, cardNums in pairs(tempCards) do
        if cardValue<41 and cardNums>=3 then
            local find = true
            for i=0, 3 do
                if tempCards[cardValue+i]==nil or tempCards[cardValue+i]<3 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.yiSeSiJieGao)
                return
            end
        end
    end
end

--检测是否一色四步高 (和牌时，牌里有4组依次递增1位数或依次递增2位数的顺子（不计一色三步高、老少副、连六）)
function logic.CheckYiSeSiBuGao(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)

    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.chi then 
            for _, card in pairs(v.oper_cards) do
                tempCards[card] = tempCards[card] + 1
            end
        end
    end

    local shunzi = logic.GetShunZi(tempCards)
    --log.info("shunzi=", shunzi)
    if #shunzi >= 4 then 
        if (shunzi[1][1]+1==shunzi[2][1] and shunzi[2][1]+1==shunzi[3][1] and shunzi[3][1]+1==shunzi[4][1]) or (shunzi[1][1]+2==shunzi[2][1] and shunzi[2][1]+2==shunzi[3][1] and shunzi[3][1]+2==shunzi[4][1]) then 
            table.insert(fanxing, def.fanXing.yiSeSiBuGao)
        end
    end
end

--检测是否三杠 (和牌时，牌里有3组杠，明暗杠均可（不计双明杠、双暗杠、明杠、暗杠）)
function logic.CheckSanGang(fanxing, handCards, cardsCombo)
    local gangNums = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if #v.oper_cards==4 then 
            gangNums = gangNums + 1
        end
    end

    --[[
    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==4 then 
            gangNums = gangNums + 1
        end
    end
    --]]

    if gangNums >= 3 then 
        table.insert(fanxing, def.fanXing.sanGang)
    end
end

--检测是否混九幺 (和牌时，牌全部由为字牌或1万、九万组成的刻子以及由字牌或〗万、九万组成的将牌（不计碰碰胡、幺九刻、全带幺）)
function logic.CheckHunJiuYao(fanxing, handCards, cardsCombo)
    --手牌查非1,9的牌
    if handCards[11]==0 and handCards[19]==0 then 
        return false
    end

    for cardValue, cardNums in pairs(handCards) do
        if cardValue<19 and cardValue>11 then 
            if cardValue==12 or cardValue==13 then 
                if cardNums~=handCards[11] and cardNums~=0 then 
                    return false
                end
            elseif cardValue==17 or cardValue==18 then 
                if cardNums~=handCards[19] and cardNums~=0 then 
                    return false
                end
            else 
                if cardNums>0 then 
                    return false
                end
            end
        end
    end
    --[[
    （组成牌不用查了）
    --组成牌查带不带1,9 
    for _, v in pairs(cardsCombo) do
        local isFind = false
        for _, card in pairs(v.oper_cards) do
            if card==11 or card==19 then 
                isFind=true
            end
        end
        if isFind==false then 
            return false
        end
    end
    --]]

    table.insert(fanxing, def.fanXing.hunJiuYao)
end

--检测是否七对 (和牌时,牌里有七组对子(不计门清、不求人、单调将))
function logic.CheckQiDui(fanxing, handCards, cardsCombo)
    local duiNums = 0
    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        --是不是风牌  （东南西北）
        if cardNums>=2 then 
            duiNums = duiNums + 1
        end
    end

    if duiNums >= 7 then 
        table.insert(fanxing, def.fanXing.qiDui)
    end
end

--检测是否清一色 (和牌时,牌全部由万字牌组成)
function logic.CheckQingYiSe(fanxing, handCards, cardsCombo)
    local result = true
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]>19 then 
            result = false
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        --是不是风牌  （东南西北）
        if cardValue>19 and cardNums>0 then 
            result = false
        end
    end

    if result == true then 
        table.insert(fanxing, def.fanXing.qingYiSe)
    end
end

--检测是否一色三同顺 (和牌时,牌里有相同的3组顺子(不计一色三节高、一般高))
function logic.CheckYiSeSanTongShun(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.chi then 
            for _, card in pairs(v.oper_cards) do
                tempCards[card] = tempCards[card] + 1
            end
        end
    end

    --相同的3组顺子其实就是3个连着的刻子
    for cardValue, cardNums in pairs(tempCards) do
        if cardNums>=3 and cardValue<41 then
            local find = true
            for i=0, 2 do
                if tempCards[cardValue+i]==nil or tempCards[cardValue+i]<3 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.yiSeSanTongShun)
                return
            end
        end
    end
end

--检测是否一色三节高 (和牌时,牌里有3组依次递增1位数的刻子(不计一色三同顺))
function logic.CheckYiSeSanJieGao(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.peng then 
            tempCards[v.oper_cards[1]] = tempCards[v.oper_cards[1]] + 3
        end
    end

    for cardValue, cardNums in pairs(tempCards) do
        if cardValue<41 and cardNums>=3 then
            local find = true
            for i=0, 2 do
                if tempCards[cardValue+i]==nil or tempCards[cardValue+i]<3 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.yiSeSanJieGao)
                return
            end
        end
    end
end

--检测是否清龙 (和牌时,牌里有1万至9万相连的九张牌(不计连六、老少副))
function logic.CheckQingLong(fanxing, handCards, cardsCombo)
    local result = true
    for cardValue=11, 19 do
        if handCards[cardValue] == 0 then 
            result = false
        end
    end

    if result == true then 
        table.insert(fanxing, def.fanXing.qingLong)
    end
end

--检测是否一色三步高 (和牌时,牌里有3组依次递增1位数或依次递增2位数的顺子)
function logic.CheckYiSeSanBuGao(fanxing, handCards, cardsCombo)
    local tempCards = logic.CopyHandCards(handCards)

    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.chi then 
            for _, card in pairs(v.oper_cards) do
                tempCards[card] = tempCards[card] + 1
            end
        end
    end

    local shunzi = logic.GetShunZi(tempCards)
    --log.info("shunzi=", shunzi)
    if #shunzi >= 3 then 
        if (shunzi[1][1]+1==shunzi[2][1] and shunzi[2][1]+1==shunzi[3][1]) or (shunzi[1][1]+2==shunzi[2][1] and shunzi[2][1]+2==shunzi[3][1])  then 
            table.insert(fanxing, def.fanXing.yiSeSanBuGao)
        end
    end
end

--检测是否三暗刻 (和牌时,牌里有3个暗刻(暗杠)(不计双暗刻))
function logic.CheckSanAnKe(fanxing, handCards, cardsCombo, huInfo)
    local anKe = 0

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=3 then 
            --anKe = anKe + 1
        end
    end

    anKe = anKe + #huInfo.huKezi

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.anGang then 
            anKe = anKe + 1
        end
    end
   
    --log.info("CheckSanAnKe huInfo=", huInfo)

    if anKe>=3 then 
        table.insert(fanxing, def.fanXing.sanAnKe)
    end
end

--检测是否大于5 (和牌时,牌全部为6万至9万的顺子、刻子、将组成)
function logic.CheckDaYu5(fanxing, handCards, cardsCombo)
    local result = true

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if (cardValue<16 and cardNums>0) or (cardValue>19 and cardNums>0) then 
            result = false
        end
    end

    --查组成
    for _, v in pairs(cardsCombo) do
        for _, card in pairs(v.oper_cards) do
            if card<16 or card>19 then 
                return false
            end
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.dayu5)
    end
end

--检测是否小于5 (和牌时,牌全部为1万至4万的顺子、刻子、将组成)
function logic.CheckXiaoYu5(fanxing, handCards, cardsCombo)
    local result = true

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>14 and cardNums>0 then 
            result = false
        end
    end

    --查组成
    for _, v in pairs(cardsCombo) do
        for _, card in pairs(v.oper_cards) do
            if card>14 then 
                return false
            end
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.xiaoyu5)
    end
end

--检测是否三风刻 (和牌时,牌里有三组风牌刻子(杠)(不计幺九刻))
function logic.CheckSanFengKe(fanxing, handCards, cardsCombo)
    local fengNums = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        --风牌只可能碰杠
        if v.oper_cards[1]>=41 and v.oper_cards[1]<=44 then 
            fengNums = fengNums + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        --是不是风牌  （东南西北）
        if (cardValue>=41 and cardNums>0) and (cardValue<=44 and cardNums>0) then 
            if cardNums >= 3 then 
                fengNums = fengNums + 1
            end
        end
    end

    if fengNums >= 3 then 
        table.insert(fanxing, def.fanXing.sanFengKe)
    end
end

--检测是否碰碰和 (和牌时,牌型由4组刻子(或杠)、将牌组成)
function logic.CheckPengPeng(fanxing, handCards, cardsCombo)
    --手牌不带顺，组成牌不带吃
    local sum = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type>=def.operType.peng then 
            sum = sum + 1
        end
    end

    --查手牌, 不能有单张
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=3 then 
            sum = sum + 1
        end
    end 

    if sum>=4 then 
        table.insert(fanxing, def.fanXing.pengpengHe)
    end
end

--检测是否混一色 (和牌时,牌型由万字牌和字牌组成)
function logic.CheckHunYiSe(fanxing, handCards, cardsCombo)
    local wanNums = 0
    local ziNums = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]>=11 and v.oper_cards[1]<=19 then 
            wanNums = wanNums + 1
        end
        if v.oper_cards[1]>=41 and v.oper_cards[1]<=47 then 
            ziNums = ziNums + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>=11 and cardValue<=19 then 
            if cardNums > 0 then 
                wanNums = wanNums + 1
            end
        end
        if cardValue>=41 and cardValue<=49 then 
            if cardNums > 0 then 
                ziNums = ziNums + 1
            end
        end
    end

    if ziNums>0 and wanNums>0 then 
        table.insert(fanxing, def.fanXing.hunYiSe)
    end
end

--检测是否双暗杠 (牌时,牌里有2组暗杠(不计双暗刻、暗杠))
function logic.CheckShuangAnGang(fanxing, handCards, cardsCombo)
    local anGang = 0

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.anGang then 
            anGang = anGang + 1
        end
    end

    --[[
    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=4 then 
            anGang = anGang + 1
        end
    end
    --]]

    if anGang>=2 then 
        table.insert(fanxing, def.fanXing.shuangAnGang)
    end
end

--检测是否双箭刻 (和牌时,牌里有2组箭牌刻子(杠)(不计箭刻))
function logic.CheckShuangJianKe(fanxing, handCards, cardsCombo)
    local jianKe = 0

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]>=45 and v.oper_cards[1]<=47 then 
            jianKe = jianKe + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>=45 and cardValue<=47 then 
            if cardNums>=3 then 
                jianKe = jianKe + 1
            end
        end
    end

    if jianKe>=2 then 
        table.insert(fanxing, def.fanXing.shuangJianKe)
    end
end

--检测是否双明杠 (和牌时,牌里有2组明杠(不计明杠))
function logic.CheckShuangMingGang(fanxing, handCards, cardsCombo)
    local mingGang = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.mingGang then 
            mingGang = mingGang + 1
        end
    end

    if mingGang==2 then 
        table.insert(fanxing, def.fanXing.shuangMingGang)
    end
end

--检测是否箭刻 (和牌时,牌里有1组箭牌组成的刻子(不计幺九刻))
function logic.CheckJianKe(fanxing, handCards, cardsCombo)
    local jianKe = 0

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]>=45 and v.oper_cards[1]<=47 then 
            jianKe = jianKe + 1
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>=45 and cardValue<=47 then 
            if cardNums>=3 then 
                jianKe = jianKe + 1
            end
        end
    end

    if jianKe>=1 then 
        table.insert(fanxing, def.fanXing.jianKe)
    end
end

--检测是否双暗刻 (和牌时，牌里有2组暗刻)
function logic.CheckShuangAnKe(fanxing, handCards, cardsCombo)
    local anKe = 0

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=3 then 
            anKe = anKe + 1
        end
    end

    if anKe>=2 then 
        table.insert(fanxing, def.fanXing.shuangAnKe)
    end
end

--检测是否暗杠 (和牌时，牌里有一组已经开杜的暗杠)
function logic.CheckAnGang(fanxing, handCards, cardsCombo)
    local anGang = 0

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.anGang then 
            anGang = anGang + 1
        end
    end

    --查手牌(后来修改为手牌不查了)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>=4 then 
            --anGang = anGang + 1
        end
    end

    if anGang>=1 then 
        table.insert(fanxing, def.fanXing.anGang)
    end
end

--检测是否断幺 (和牌时，牌里没有1万、9万及字牌)
function logic.CheckDuanYao(fanxing, handCards, cardsCombo)
    local result = true

    --查组成的牌
    for _, v in pairs(cardsCombo) do
        for _, cardValue in pairs(v.oper_cards) do
            if cardValue==11 or cardValue==19 then  
                result = false
            end
        end
    end

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue==11 or cardValue==19 then 
            if cardNums>0 then 
                result = false
            end
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.duanYao)
    end
end

--检测是否一般高 (和牌时，牌里有相同的2组顺子)
function logic.CheckYiBanGao(fanxing, handCards, cardsCombo)
    --相同的2组顺子其实就是3个连着的对子
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==2 and cardValue<41 then
            local find = true
            for i=0, 2 do
                if handCards[cardValue+i]==nil or handCards[cardValue+i]<2 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.yiBanGao)
                return
            end
        end
    end
end

--检测是否连6 (和牌时，牌里有6张数字相连的万字牌)
function logic.CheckLianLiu(fanxing, handCards, cardsCombo)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums>0 and cardValue<19 then
            local find = true
            for i=0, 5 do
                if handCards[cardValue+i]==nil or handCards[cardValue+i]<1 then 
                    find = false
                    break
                end
            end
            if find==true then 
                table.insert(fanxing, def.fanXing.lianLiu)
                return
            end
        end
    end
end

--检测是否老少副 (和牌时，牌里有123万、789万顺子各1组)
function logic.CheckLaoShaoFu(fanxing, handCards, cardsCombo)
    local index = {
        11,12,13,
        17,18,19,
    }

    local find = true
    for _, v in pairs(index) do
        if handCards[v]<1 then 
            find = false
            break
        end
    end

    if find==true then 
        table.insert(fanxing, def.fanXing.laoshaoFu)
    end
end

--检测是否幺九刻 (和牌时，牌里有1万、9万或字牌的1组刻子)
function logic.CheckYaoJiuKe(fanxing, handCards, cardsCombo)
    local result = false

    --查手牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue==11 or cardValue==19 then 
            if cardNums>=3 then 
                result = true
            end
        elseif cardValue>=41 and cardNums>=3 then 
            result = true
        end
    end

    if result==true then 
        table.insert(fanxing, def.fanXing.yaoJiuKe)
    end
end

--检测是否明杠 (和牌时，牌里有已经幵杠的明杠)
function logic.CheckMingGangFan(fanxing, handCards, cardsCombo)
    local mingGang = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.mingGang then 
            mingGang = mingGang + 1
        end
    end

    if mingGang==1 then 
        table.insert(fanxing, def.fanXing.mingGang)
    end
end

----------------------------------------------
--检测是否天胡 (庄家开牌后就和牌,称为天和。若庄家在开牌后有开杠(包括暗杠),则不算天和(不计单调将、边张、砍张)）
function logic.CheckTianHu(fanxing, handCards, cardsCombo)
end

--检测是否地胡 (闲家摸到第一张牌就和牌,称为地和)
function logic.CheckDiHu(fanxing, handCards, cardsCombo)
end

--检测是否人和（庄家打岀的第一张牌被闲家和牌,称为人和）
function logic.CheckRenHu(fanxing, handCards, cardsCombo)
end

--检测是否天听 (庄家打岀第一张牌时听牌或闲家13张牌一发到手就听牌了称为天听。若庄家在发完牌后有开杠,则不算夭听(不计立直、报听）)
function logic.CheckTianTing(fanxing, handCards, cardsCombo)
end

--检测是否妙手回春 (和牌时,自摸牌墙上最后一张牌(不计自摸))
function logic.CheckMiaoShou(fanxing, handCards, cardsCombo)
end

--检测是否海底捞月 (和牌时,和的牌为对家打出的最后一张牌)
function logic.CheckHaiDi(fanxing, handCards, cardsCombo)
end

--检测是否杠上开花 (和牌时,和的牌为开杠后的补牌(不计自摸))
function logic.CheckGangHua(fanxing, handCards, cardsCombo)
end

--检测是否全求人 (和牌时,全靠吃牌、碰牌(开杠)、单调别人打出的牌和牌(不计单调将))
function logic.CheckQuanQiuRen(handCards, cardsCombo, huCard, dianPaoRen)
    local result = true
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.anGang or v.oper_type==def.operType.buGang then 
            result = false
        end
    end

    --检测手牌，胡的那张牌是单调的，也就是必定胡的是将
    if handCards[huCard]~=2 then 
        result = false
    end

    if dianPaoRen==def.maxValue then 
        result = false
    end
   
    return result
end

--检测是否全带幺 (和牌时,各组刻子、杠、顺子、将牌都带有万字牌或1万或九万)
function logic.CheckQuanDaiYao(fanxing, handCards, cardsCombo)
    --手牌查非1,9的牌
    for cardValue, cardNums in pairs(handCards) do
        if cardValue>19 and cardNums>0 then 
            return false
        else
            if cardNums>0 then 
                if cardValue==12 or cardValue==13 then 
                    if cardNums~=handCards[11] then 
                        --return false
                    end
                elseif cardValue==17 or cardValue==18 then 
                    if cardNums~=handCards[19] then 
                        --return false
                    end
                elseif cardValue==11 or cardValue==19 then
                    --
                else 
                    return false
                end
            end
        end
    end

    if (handCards[12]~=handCards[13]) or (handCards[17]~=handCards[18]) then 
        return false 
    end

    --组成牌查带不带1,9
    for _, v in pairs(cardsCombo) do
        local isFind = false
        for _, card in pairs(v.oper_cards) do
            if card==11 or card==19 then 
                isFind=true
            end
        end
        if isFind==false then 
            return false
        end
    end

    table.insert(fanxing, def.fanXing.quanDaiYao)
end

--检测是否不求人 (和牌时,没有吃牌、碰牌、杠对方的牌,且自摸和牌(不计门前清、自摸))
function logic.CheckBuQiuRen(cardsCombo, dianPaoRen)
    local result = true
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type~=def.operType.anGang then 
            result = false
        end
    end
    
    if dianPaoRen~=def.maxValue then 
        result = false
    end

    return  result
end

--检测是否胡绝章 (和牌时,桌面已明亮的3张牌所剩的第4张牌(不计抢杠胡))
function logic.CheckHuJueZhang(huCard, allSeeCards)
    local seeNums = 0
    for _, v in pairs(allSeeCards) do
        if v==huCard then 
            seeNums = seeNums + 1
        end
    end

    if seeNums >= 3 then 
        return true
    end

    return false
end

--检测是否立直 (门前清且听牌后和牌(不计报听、门前清))
function logic.CheckLiZhi(fanxing, handCards, cardsCombo)
end

--检测是否圈风刻 (和牌时,牌里有与圈风相同的风牌刻子(不计幺九刻))
function logic.CheckQuanFengKe(handCards, cardsCombo)
    --胡牌时有风刻且该风刻是庄家的位置（庄家永远东风） 东风对面西风
    local result = false

    local dongFengNums = 0
    --手牌
    if handCards[41]>=3 then 
        dongFengNums = dongFengNums + 1
    end
    --组成牌查带不带东风
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]==41 then 
            dongFengNums = dongFengNums + 1
        end
    end

    if dongFengNums > 0 then 
        result = true
    end

    return result
end

--检测是否门风刻 (和牌时,牌里有与门风相同的风牌刻子(不计幺九刻）)
function logic.CheckMenFengKe(handCards, cardsCombo, isBank)
    --胡牌时有风刻且该风刻是自己的位置
    local result = false

    local fengNums = 0
    local index
    --庄家永远东风，闲家在西风
    if isBank==true then 
        index = 41
    else
        index = 43
    end

    --手牌
    if handCards[index]>=3 then 
        fengNums = fengNums + 1
    end
    --组成牌查带不带东风
    for _, v in pairs(cardsCombo) do
        if v.oper_cards[1]==index then 
            fengNums = fengNums + 1
        end
    end

    if fengNums > 0 then 
        result = true
    end

    return result
end

--检测是否门前清 (和牌时，没有吃、碰、明杠、和牌是别人的打出的牌) 
function logic.CheckMenQianQing(cardsCombo, dianPaoRen)
    local result = true
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type~=def.operType.anGang then 
            result = false
        end
    end

    if dianPaoRen==def.maxValue then 
        result = false
    end

    return result
end

--检测是否平和 (和牌时，牌型甶4组顺子和万字牌做将组成)
function logic.CheckPingHu(handCards, cardsCombo)
    local result = true

    local nums = 0
    --查组成的牌
    for _, v in pairs(cardsCombo) do
        if v.oper_type==def.operType.chi then 
            nums = nums + 1
        end
    end

    local huInfo = logic.CheckHu(handCards)
    if huInfo.isHu==true then 
        nums = nums + #huInfo.huShunzi
        if huInfo.huJiang[1] > 19 then 
            result = false
        end 
    end

    if result==true and nums>=4 then 
        return true
    end

    return false
end

--检测是否四归 (和牌时，牌里有4张相同的牌归于1家的顺、刻子、将牌，不包括开杠)
function logic.CheckSiGui(fanxing, handCards, cardsCombo)
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==4 then 
            table.insert(fanxing, def.fanXing.siGui)
            break
        end
    end
end

function logic.CheckHuEwbj(handCards)
    local huInfo = {
        isHu = false,
        huJiang = {},
        huKezi = {},
        huShunzi = {},
    }

    local tempHandCards = logic.CopyHandCards(handCards)
    local tempHandCards2 = logic.CopyHandCards(tempHandCards) 

    --local ewbj = {12, 15, 18, 22, 25, 28, 32, 35, 38}
    local ewbj = { 18}
    --分别计算以不同 "将" 情况下胡牌情况
    for k, v in pairs(ewbj) do
        if tempHandCards[v] and tempHandCards[v]>=2 then 
            local theCards = logic.CopyHandCards(tempHandCards)
            theCards[v] = theCards[v] - 2
            log.info("after jiang handCards=", theCards)
            --先取所有顺子
            local shunzi = logic.GetShunZi(theCards)
            log.info("after GetShunZi handCards=", theCards)
            --再取所有刻子
            local kezi = logic.GetKeZi(theCards)
            log.info("after GetKeZi handCards=", theCards)

            --若手牌完全取完，则代表是胡牌
            local isHu = true
            for _, cardNums in pairs(theCards) do
                if cardNums > 0 then 
                    isHu = false
                end
            end
            --胡了
            if isHu then
                huInfo.isHu = true 
                huInfo.huJiang = {k}
                huInfo.huKezi = kezi
                huInfo.huShunzi = shunzi
                return huInfo
            end
        end
    end

    log.info("Change Steps!!!")
    for k, v in pairs(ewbj) do
        if tempHandCards2[v] and tempHandCards2[v]>=2 then 
            local theCards = logic.CopyHandCards(tempHandCards2)
            theCards[v] = theCards[v] - 2
            log.info("after jiang handCards=", theCards)
            --先取所有刻子
            local kezi = logic.GetKeZi(theCards)
            log.info("after GetKeZi handCards=", theCards)
            --再取所有顺子
            local shunzi = logic.GetShunZi(theCards)
            log.info("after GetShunZi handCards=", theCards)
            
            --若手牌完全取完，则代表是胡牌
            local isHu = true
            for _, cardNums in pairs(theCards) do
                if cardNums > 0 then 
                    isHu = false
                end
            end
            --胡了
            if isHu then
                huInfo.isHu = true 
                huInfo.huJiang = {k}
                huInfo.huKezi = kezi
                huInfo.huShunzi = shunzi
                return huInfo
            end
        end
    end

    return huInfo
end

--检测是否二五八将 (和牌时，将牌是2万、5万或8万)
function logic.CheckEwbj(handCards)
    local result = false

    --local huInfo = logic.CheckHuEwbj(handCards)
    local huInfo = logic.CheckHu(handCards)
    if huInfo.isHu==true then 
        if huInfo.huJiang[1]==12 or huInfo.huJiang[1]==15 or huInfo.huJiang[1]==18 then 
            result = true
        end
    end
    
    return result
end

--检测是否幺九头 (和牌时将牌是1万或9万)
function logic.CheckYaoJiuTou(handCards)
    local result = false

    local nums = 0
    for cardValue, cardNums in pairs(handCards) do
        if cardNums==2 then 
            if cardValue==11 or cardValue==19 then 
                result = true
            end
        end
    end

    return result
end

--检测是否报听 (听牌后和牌)
function logic.CheckBaoTing()
end


--检测是否边张 (单和123的3或7789的7都为边张，12345和3不算边张)
function logic.CheckBianZhang(handCards, huCard)
    if handCards[huCard]==1 and (handCards[huCard-1]==0 or handCards[huCard+1]==0) then 
        return true
    end
end

--检测是否坎张 (和牌时，和2张牌之间的牌。4556和5也算坎张，45567和6不算坎张)
function logic.CheckKanZhang(handCards, huCard)
    local huInfo = logic.CheckHu(handCards)

    local iRet = false
    for _, v in pairs(huInfo.huShunzi) do
        if v[2]==huCard then 
            iRet =  true 
        end
    end

    --两边只能是单张
    if (handCards[huCard-1] and handCards[huCard-1]>1) or  (handCards[huCard+1] and handCards[huCard+1]>1) then 
        iRet = false
    end

    return iRet
end

--检测是否单调将 (和单张牌，并且该张单牌为整副牌的将牌)
function logic.CheckDanDiaoJiang(handCards, huCard)
    --检测手牌，胡的那张牌是单调的，也就是必定胡的是将
    if handCards[huCard]~=2 then 
        result = false
    end

    return true
end

--检测是否自摸 (和自己抓进的牌)
function logic.CheckIsZimo(fanxing, handCards, cardsCombo)

end

--检测是否花牌 (胡牌时，每张花牌+1番)
function logic.CheckHuaPai(fanxing, handCards, cardsCombo)
end

--检测番型表里是否有该番
function logic.CheckFanTable(fanxing, fan)
    for _, v in pairs(fanxing) do
        if v==fan then 
            return true
        end
    end

    return false
end

--检测番型是否已冲突 
function logic.CheckFanXingClash(fanxingTable)
    for fanxing, clashFanTable in pairs(def.ClashFan) do
        --一一遍历产生的当前番型表里是否含有冲突番型
        if logic.CheckFanTable(fanxingTable, fanxing)==true then 
            for _, clashFan in pairs(clashFanTable) do
                for k, v in pairs(fanxingTable) do
                    if v==clashFan then 
                        fanxingTable[k] = nil
                    end
                end
            end
        end
    end

    local temp = {}
    for _, v in pairs(fanxingTable) do
        if v~=nil then 
            table.insert(temp, v)
        end
    end

    return temp
end

local function __keep_decimal(s, n, up)      --保留n位小数,up为true是保留至向上,否则是抹去
    n = n or 2
    if n < 0 then
        return s
    end
    local is_str = false
    if type(s) == 'string' then
        s = tonumber(s)
        is_str = true
    end
    local inte = math.tointeger(s)
    if inte then           --已经是整数
        return inte
    end
    if s then
        local x = s % 1
        if x > 0 then      --小数部分
            local xd = string.sub(x, 1, 2 + n)
            local ret = math.floor(s) + tonumber(xd)
            if up then
                if math.abs(s - ret) > 1e-5 then    --必须这么比较
                    ret = ret + 0.1^n
                end
            end
            s = ret
        end
    end
    if is_str then
        s = tostring(s) or 0
    end
    return s or 0
end

----------------------------------------------
--向上取小数点后2位，（第三位非0则进1）
function logic.CalcHigh(num)
    local ret, value = pcall(__keep_decimal, num, 2, true)
    if ret==false then 
        log.error("__keep_decimal error num=", num)
        log.error("return msg: ", value)
        return tonumber( string.format("%0.2f", num) )
    end

    return value
end

--向下取小数点后2位（从第3位开始全部舍去）
function logic.CalcLow(num)
    local ret, value = pcall(__keep_decimal, num, 2, false)
    if ret==false then 
        log.error("__keep_decimal error num=", num)
        log.error("return msg: ", value)
        return tonumber( string.format("%0.2f", num) )
    end

    return value
end

------------------------------------------------------------


function logic:init(room_info)
    log.debug("logic init!")
   
end

function logic:join_room_notify()
    log.debug("logic join_room_notify!")
end

function logic:leave_room_notify()
    log.debug("logic leave_room_notify!")
end

function logic:dissmiss_room_notify()
    log.debug("logic dissmiss_room_notify!")
end

function logic:game_start_notify(agent, room)
    log.debug("logic game_start_notify!")

    --init(room)
end



return logic
